package icom.acm.util.mongo;
/**
 * @author shench
 * MongoDB 数据库管理类
 */

import icom.acm.util.DateUtil;
import icom.acm.util.spring.SpringFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;

public class MongoDB {
	private static MongoDB dm;
	
	private Mongo mongo;	// MongoDB
	private DB db;			// 一个数据库
	private DBCollection col;	// 数据库集合 相当与结果及
	private DBCursor cur;		// 数据游标
	
	public static synchronized MongoDB newInstance(){
		SpringFactory sf = SpringFactory.newInstance();
		
		if (dm == null)
			dm = (MongoDB)(sf.action(sf.bean, "MongoDB"));
		dm.col = null;
		dm.cur = null;
		return dm;
	}
	
	public MongoDB(){
		
	}
	
	public MongoDB(Mongo mongo, String dbname, 
			String admin, String password){		
		this.mongo = mongo;
		
		db = mongo.getDB(dbname);
		boolean auth = db.authenticate(admin, password.toCharArray());
		if (auth==false) {
			new Exception("用户密码失败").printStackTrace();
			db = null; 		
		}
	}
	
	/**
	 * 根据map得到所有对应的表
	 * 用于数据初始化
	 * @param map
	 */
	public MongoDB(HashMap<String, String[]> map){
		this();
		createIndexs(map);
	}
	
	
	/**
	 * 创建 索引，批量
	 * @param map
	 */
	public void createIndexs(HashMap<String, String[]> map){
		java.util.Iterator<Entry<String , String[]>> it = map.entrySet().iterator();
		while (it.hasNext()){
			Entry<String , String[]> e = it.next();
			DBCollection c = db.getCollection(e.getKey());
			String[] args = e.getValue();
			BasicDBObject dbo = new BasicDBObject();
			for (int i=0;i<args.length;i++){
				dbo.append(args[i], 1);
			}
			createIndex(c, dbo);
		}	
	}
	/**
	 * 对arg集合创建idx条件的索引
	 * @param arg
	 * @param idx
	 */
	public void createIndex(DBCollection arg, BasicDBObject idx){
		arg.createIndex(idx);
	}
	
	/**
	 * 构建数据库链接
	 */
/*	public boolean build(){		
		try {			
			mongo = new Mongo(StaticData.mongoBean.getAddress(), 
							 StaticData.mongoBean.getPort());				
			MongoOptions options = mongo.getMongoOptions();
			options.autoConnectRetry = StaticData.mongoOptions.autoConnectRetry;  
            options.connectionsPerHost = StaticData.mongoOptions.connectionsPerHost;
            options.threadsAllowedToBlockForConnectionMultiplier = StaticData.mongoOptions.threadsAllowedToBlockForConnectionMultiplier;
            options.connectTimeout = StaticData.mongoOptions.connectTimeout;
            options.maxAutoConnectRetryTime = StaticData.mongoOptions.maxAutoConnectRetryTime;
            options.maxWaitTime = StaticData.mongoOptions.maxWaitTime;            
            
			db = mongo.getDB(StaticData.mongoBean.getDatabase());			
			boolean auth = db.authenticate(StaticData.mongoBean.getUsername(), StaticData.mongoBean.getPassword().toCharArray());
			if (auth==false) return false; 
		} catch (UnknownHostException e) {
			e.printStackTrace();
			return false;
		} catch (MongoException e) {
			e.printStackTrace();
			return false;
		}		
		return true;
	}*/
	
	/**
	 * 摧毁一个数据库的链接
	 */
    public void destory() {    
        if (mongo != null)    
            mongo.close();    
        mongo = null;    
        db = null;                    
        System.gc();  
    }
    
   
    
    public Set<String> getCollectionNames(){
    	return db.getCollectionNames();
    }
    
    public DBCollection getCollection(String arg){
    	col = db.getCollection(arg);
    	return col;
    }
    
    /**
     * 插入一段数据
     * @param obj
     * @return
     */
    public int insert(DBObject obj){    	
    	return col.save(obj).getN();
    }
    /**
     * 插入多条数据
     * @param objs
     * @return
     */
    public int insert(List<DBObject> objs){
    	return col.insert(objs).getN();
    }
    /**
     * 根据arg对象条件删除记录
     * @param arg
     */
    public void remove(DBObject arg){
    	col.remove(arg);
    }
    /**
     * 根据query条件更改数据为update
     * @param query
     * @param update
     * @return
     */
    public DBObject modify(DBObject query, DBObject update){
    	return col.findAndModify(query, update);
    }
    
    /**
     * 得到数据数目
     * @return
     */
    public long count(){
    	return col.getCount();
    }
    /**
     * 返回添加条件对象
     * @param src 原条件
     * @param key 主键
     * @param ftype 条件类型
     * @param value 对比值
     * @param type 值类型
     * @return
     */
    public BasicDBObject addTerm(BasicDBObject src, 
    		String key, String ftype, String value, int type){   
    	Object v = null;
    	
    	if (type==FieldMongoType.INTEGER){
    		v = Integer.parseInt(value);
    	} else if (type==FieldMongoType.LONG){
    		v = Long.parseLong(value);
    	} else if (type==FieldMongoType.BOOLEAN){
    		v = Boolean.valueOf(value);
    	} else if (type==FieldMongoType.STRING){
    		v = value;
    	} else if (type==FieldMongoType.DATE){
    		v = DateUtil.s2d("yyyy-MM-dd HH:mm:ss", value);
    	}
  	
    	if (ftype.equals(FieldMongoType.EQUAL)){
    		src.append(key, v);  
    	} else {
    		src.append(ftype, v);
    	}
    	
    	return src;
    }
    
    public void batchSize(int n){
    	cur = cur.batchSize(n);
    }
    
    /**
     * 根据arg对象条件 得到cur
     * @param arg
     */
    public void find(DBObject arg){
    	cur = col.find(arg);    	
    }
        
    /**
     * 找到所有记录
     */
    public void find(){
    	cur = col.find();
    }
    /**
     * 找到一条记录
     */
    public DBObject find1(){
    	return col.findOne();
    }
    /**
     * 查看游标是否还有数据
     * @return
     */
    public boolean hasNext(){
    	return cur.hasNext();
    }
    /**
     * 从游标中得到下一个数据
     * @return
     */
    public DBObject next(){
    	return cur.next();
    }
}
